package com.sz.biz.logistics.ord.service.impl;

import com.sz.biz.common.constants.CommCodes;
import com.sz.biz.common.constants.ModuleNames;
import com.sz.biz.logistics.core.entity.Service;
import com.sz.biz.logistics.core.service.ProductServiceRelService;
import com.sz.biz.logistics.core.service.ServiceService;
import com.sz.biz.logistics.ord.constants.OrderTrackingConstants;
import com.sz.biz.logistics.ord.dto.OrdOrderOptionService;
import com.sz.biz.logistics.ord.dto.OrdServiceOrderDto;
import com.sz.biz.logistics.ord.dto.TrackingToSupOrder;
import com.sz.biz.logistics.ord.entity.OrdOrder;
import com.sz.biz.logistics.ord.entity.OrdServiceOrder;
import com.sz.biz.logistics.ord.entity.OrdTrackingMessage;
import com.sz.biz.logistics.ord.enums.TrackMessageToServiceEnum;
import com.sz.biz.logistics.ord.service.OrdOrderServiceAssignService;
import com.sz.biz.logistics.ord.service.OrdOrderTrackingService;
import com.sz.biz.logistics.ord.service.OrdServiceOrderService;
import com.sz.biz.logistics.ord.service.OrdSubOrderService;
import com.sz.common.base.constants.UserActions;
import com.sz.common.base.dao.ParamData;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.service.AbstractService;
import com.sz.common.base.utils.EntityUtils;
import com.sz.common.base.utils.JsonUtils;
import com.sz.common.core.service.PrincipalLogUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.util.*;

/**
 * Function: 服务订单信息 <br>
 * Author: hpeng.wang. <br>
 * Date: 2017-03-31 13:54:00.
 */
@org.springframework.stereotype.Service("ordServiceOrderService")
public class OrdServiceOrderServiceImpl extends AbstractService implements OrdServiceOrderService {

    @Autowired
    private OrdOrderTrackingService ordOrderTrackingService;
    @Autowired
    private OrdTrackingMessageServiceImpl trackingMessageService;
    @Autowired
    private OrdOrderServiceAssignService orderServiceAssignService;

    @Autowired
    private OrdSubOrderService subOrderService;


    @Autowired
    private ProductServiceRelService productServiceRelService;

    @Autowired
    private ServiceService serviceService;

    @Override
    protected String getMapperNamespace() {
        return "com.sz.biz.logistics.ord.entity.mapper.OrdServiceOrderMapper";
    }

    @Override
    public String saveServiceOrderDto(OrdServiceOrderDto serviceOrderDto) {
        String serviceOrderNo = "";
        if (!ObjectUtils.isEmpty(serviceOrderDto)) {
            OrdServiceOrder serviceOrder = new OrdServiceOrder();
            EntityUtils.copyPropertiesIgnoreNull(serviceOrderDto, serviceOrder);
            this.saveServiceOrder(serviceOrder);
            // TODO  serviceOrderNo = serviceOrder.getServiceOrderNo();//取得订单编号
        }
        return serviceOrderNo;
    }

    @Override
    public OrdServiceOrder save(OrdServiceOrder ordServiceOrder) {
        return saveServiceOrder(ordServiceOrder);
    }

    @Override
    public void batchDeleteByServiceOrderNos(List<String> serviceOrderNos) {
        if (!CollectionUtils.isEmpty(serviceOrderNos)) {
            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("DELETE_ORD_SERVICE_ORDER", serviceOrderNos);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.DELETE, "删除服务订单", dataBackup);

            //删除数据
            dao.batchDelete(getSqlName("deleteByServiceOrderNo"), serviceOrderNos);
        }

    }

    @Override
    public void updateDtoByServiceOrderNo(OrdServiceOrderDto serviceOrderDto) {
        if (!ObjectUtils.isEmpty(serviceOrderDto)) {
            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("SAVE_ORD_SERVICE_ORDER", serviceOrderDto);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "更新服务订单", dataBackup);
            batchUpdateDtoByServiceOrderNos(Arrays.asList(serviceOrderDto));
        }
    }

    @Override
    public void updateStatusByServiceOrderNo(String serviceOrderNo) {
        if (StringUtils.hasLength(serviceOrderNo)) {
            dao.update(getSqlName("updateStatusByServiceOrderNo"), serviceOrderNo);

            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("SAVE_ORD_SERVICE_ORDER", serviceOrderNo);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "更新服务订单", dataBackup);
        }
    }

    @Override
    public OrdServiceOrderDto findDtoByServiceOrderNo(String serviceOrderNo) {
        OrdServiceOrderDto serviceOrderDto = null;
        if (StringUtils.hasLength(serviceOrderNo)) {
            List<OrdServiceOrderDto> orderDtoList = findDtoByServiceOrderNos(Arrays.asList(serviceOrderNo));
            if (!CollectionUtils.isEmpty(orderDtoList)) {
                serviceOrderDto = orderDtoList.get(0);
            }
        }
        return serviceOrderDto;
    }

    @Override
    public OrdServiceOrder findUnFinishByServiceOrderNo(String serviceOrderNo) {
        OrdServiceOrder serviceOrder = null;
        if (StringUtils.hasLength(serviceOrderNo)) {
            serviceOrder = (OrdServiceOrder) dao.findForObject(getSqlName("findUnFinishByOrderNo"), serviceOrderNo);
        }
        return serviceOrder;
    }

    @Override
    public QResultDto findDtoByParam(QueryParams params) {
        ParamData pd = convertQueryParams(params);
        //1、根据条件查询相应的订单编号
        List<OrdServiceOrder> serviceOrderList = dao.findForList(getSqlName("findServiceOrderNoByParamListPage"), pd, OrdServiceOrder.class);
        //2、拼装serviceOrderDto
        List<OrdServiceOrderDto> serviceOrderDtoList = getServiceOrderDtos(serviceOrderList);
        //3、返回数据
        return new QResultDto(serviceOrderDtoList, pd.getPagination());
    }


    /**
     * 根据服务订单，保存服务订单
     *
     * @param serviceOrder 新增的实体
     * @return 新增是否成功
     */
    private OrdServiceOrder saveServiceOrder(OrdServiceOrder serviceOrder) {
        if (!ObjectUtils.isEmpty(serviceOrder)) {


            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("SAVE_ORD_SERVICE_ORDER", serviceOrder);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "更新服务订单", dataBackup);


            dao.save(getSqlName("insertSelective"), serviceOrder);
        }
        return serviceOrder;
    }


    /**
     * 批量更新服务订单dto
     *
     * @param serviceOrderDtoList 要处理的服务订单dto
     */
    private void batchUpdateDtoByServiceOrderNos(List<OrdServiceOrderDto> serviceOrderDtoList) {
        if (!CollectionUtils.isEmpty(serviceOrderDtoList)) {
            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("UPDATE_ORD_SERVICE_ORDER", serviceOrderDtoList);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "修改服务订单", dataBackup);

            //3、对要保存的数据进行数据保存
            List<OrdServiceOrder> serviceOrderList = new ArrayList<>();
            //3.1、对集合便利
            for (OrdServiceOrderDto serviceOrderDto : serviceOrderDtoList) {
                //处理服务订单
                OrdServiceOrder serviceOrder = new OrdServiceOrder();
                EntityUtils.copyPropertiesIgnoreNull(serviceOrderDto, serviceOrder);
                serviceOrder.setLastUpdateTime(null);//数据由数据库来维护
                serviceOrder.setCreateTime(null);//数据由数据库来维护
                serviceOrderList.add(serviceOrder);
            }
            //3.2、保存要更改的数据
            batchUpdateByServiceOrderNo(serviceOrderList);
        }
    }

    /**
     * 根据服务订单集合（serviceOrderNos）查询相应的服务订单信息
     *
     * @param serviceOrderNos 要查询的服务订单集合信息
     * @return 服务订单信息
     */
    private List<OrdServiceOrder> findByServiceOrderNos(List<String> serviceOrderNos) {
        List<OrdServiceOrder> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(serviceOrderNos)) {
            ParamData pd = new ParamData();
            pd.put("serviceOrderNos", serviceOrderNos);
            list = dao.findForList(getSqlName("findByServiceOrderNos"), pd, OrdServiceOrder.class);
        }
        return list;
    }

    /**
     * 根据服务订单集合（serviceOrderNos）查询相应的服务订单dto信息
     *
     * @param serviceOrderNoList 要查询的服务订单集合信息
     * @return 服务订单dto信息
     */
    private List<OrdServiceOrderDto> findDtoByServiceOrderNos(List<String> serviceOrderNoList) {
        List<OrdServiceOrder> serviceOrderList = findByServiceOrderNos(serviceOrderNoList);
        List<OrdServiceOrderDto> serviceOrderDtoList = getServiceOrderDtos(serviceOrderList);
        return serviceOrderDtoList;
    }

    /**
     * 根据服务订单获取服务订单的dto信息
     *
     * @param serviceOrderList 服务订单的订单id集合
     * @return 服务订单dto信息
     */
    private List<OrdServiceOrderDto> getServiceOrderDtos(List<OrdServiceOrder> serviceOrderList) {
        //2、根据上面查询出来的信息拼装要返回给前端的dto集合信息（serviceOrderDtoList）
        List<OrdServiceOrderDto> serviceOrderDtoList = new ArrayList<>();//存放拼装好的orderDto信息
        for (OrdServiceOrder serviceOrder : serviceOrderList) {//向产品订单中设置子订单信息与商品明细信息
            //2.1、将ordOrder对象转成ordOrderDto对象
            OrdServiceOrderDto serviceOrderDto = new OrdServiceOrderDto();
            EntityUtils.copyPropertiesIgnoreNull(serviceOrder, serviceOrderDto);
            serviceOrderDtoList.add(serviceOrderDto);
        }
        return serviceOrderDtoList;
    }

    /**
     * 批量更新服务订单（ord_service_order）数据
     *
     * @param serviceOrderList
     */
    private void batchUpdateByServiceOrderNo(List<OrdServiceOrder> serviceOrderList) {
        if (!CollectionUtils.isEmpty(serviceOrderList)) {

            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("update_ORD_SERVICE_ORDER", serviceOrderList);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "更新服务订单", dataBackup);


            dao.batchUpdate(getSqlName("updateByServiceOrderNoSelective"), serviceOrderList);
        }
    }

    /**
     * 根据订单编号修改对应的服务商订单的状态
     *
     * @param orderNo:             订单的编号
     * @param serviceUid:服务商的编号
     * @param serviceStatus:要修改的状态
     */
    @Override
    public void updateStatus(String orderNo, String serviceUid, Integer serviceStatus) {
        ParamData pd = new ParamData();
        pd.put("orderNo", orderNo);
        pd.put("serviceUid", serviceUid);
        pd.put("serviceStatus", serviceStatus);
        dao.update(getSqlName("updateStatusByorderNo"), pd);


        //数据备份
        Map<String, Object> dataBackup = new HashMap<>();
        dataBackup.put("update_ORD_SERVICE_ORDER", orderNo + "--" + serviceUid + "--" + serviceStatus);
        PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "更新服务订单", dataBackup);


    }

    @Override
    public OrdServiceOrder findByOrderNo(String orderNo, String serviceUid) {
        ParamData pd = new ParamData();
        pd.put("orderNo", orderNo);
        pd.put("serviceUid", serviceUid);
        OrdServiceOrder ordServiceOrder = (OrdServiceOrder) dao.findForObject(getSqlName("findByOrderNo"), pd);
        return ordServiceOrder;
    }

    /**
     * 1. 当前服务商-供应商对该子单的工作是否已经完成，处理是否需要给下一个供应商下订单，以及是否发一个tracking
     * 2. 当前服务商-供应商的工作是否完成，更新当前服务订单的状态
     * code 不以2开头，才进行处理. 2 是系统处理的
     */
    @Override
    public void processAfterTracking(int status, String code, String serviceUid, OrdOrder order) {
        if (CommCodes.TRACKING_STATUS_FINISH == status
                && !code.startsWith(CommCodes.ORD_STATUS_CODE_PREFIX_OPERATE)) {
            //1、给下一个供应商发送物流消息
            this.sendTrackingToNextService(serviceUid, order);

           /* *//**
             * 当前服务商-供应商的工作是否完成，更新当前服务订单的状态
             * 当前供应商返回的消息表明当前服务商-供应商针对本子订单的工作已经完成，需要检查当前服务商-供应商针对本订单的工作是否完成
             *   从tracking表中找到当前服务商-供应商对当前订单对应的子订单中收到了已经完成状态的子订单号finishedSubOrdNos，
             *   从子订单表中找到当前订单所有的子订单号originalSubOrdNos，
             *   如果finishedSubOrdNos 全部包含的有originalSubOrdNos,则表示这个服务商的工作已经完成，更新这个服务商的服务状态为已经完成
             *//*
            List<String> finishedSubOrdNos = ordOrderTrackingService.getFinishedSubOrdNos(ordOrderTracking.getOrderNo(), ordOrderTracking.getServiceUid(), CommCodes.TRACKING_STATUS_FINISH);
            List<String> originalSubOrdNos = subOrderService.getSubOrdNos(ordOrderTracking.getOrderNo());
            if (finishedSubOrdNos.containsAll(originalSubOrdNos)) {
                //该服务商的工作环节完成，更新对应的服务商订单（serviceOrder）的状态为已经完成，
                updateStatus(ordOrderTracking.getOrderNo(), ordOrderTracking.getServiceUid(), CommCodes.SERVICE_ORDER_STATUS_END);
            }*/
        }
    }

    /**
     * 给下一个供应商发送物流消息
     *
     * @param serviceUid 服务商的uid
     * @param order      订单信息
     */
    private void sendTrackingToNextService(String serviceUid, OrdOrder order) {
        //1、根据服务商-供应商对该子单的工作是否已经完成，处理是否需要给下一个供应商下订单
        OrdOrderOptionService orderOptionService = orderServiceAssignService.findNextServices(order.getOrderNo(), serviceUid);
        //如果还有下一个服务----供应商
        if (!ObjectUtils.isEmpty(orderOptionService)) {
            //1.1、得到要发前信息的服务商信息
            Date date = order.getReceiveCargoTime();
            if (ObjectUtils.isEmpty(date)) {
                date = order.getCreateTime();
            }
            Service service = serviceService.findByUidAndTime(orderOptionService.getServiceUid(), date);//得到服务商的

            //1.2、通知下个供应商来继续取货
            OrdTrackingMessage trackingMessage = new OrdTrackingMessage();
            //设置原始物流信息的id为0，表示没有原始物流信息
            trackingMessage.setMessageTime(dao.getDbDate());
            trackingMessage.setServiceUid(orderOptionService.getServiceUid());
            trackingMessage.setEventCode(TrackMessageToServiceEnum.PLACE_TRADE_ORDER.getCode());
            trackingMessage.setStatus(OrderTrackingConstants.TrackingStatus.TRACKING_STATUS_NUSYNC);
            trackingMessage.setSupplierId(service.getSupplierId());
            TrackingToSupOrder dto = ordOrderTrackingService.processSubOrderTracking(order.getOrderNo());
            trackingMessage.setTrackingReport(JsonUtils.toJSONString(dto));
            trackingMessage.setType(OrderTrackingConstants.TrackingType.TRACKING_TYPE_SYSTEM);
            trackingMessage.setWaybillNo(order.getWaybillNo());
            trackingMessage.setDescription("物流消息");
            trackingMessageService.save(trackingMessage);
        }
    }


    @Override
    public void batchSave(List<OrdServiceOrder> serviceOrderList) {
        if (!CollectionUtils.isEmpty(serviceOrderList)) {
            dao.batchInsert(getSqlName("insertSelective"), serviceOrderList);

            //数据备份
            Map<String, Object> dataBackup = new HashMap<>();
            dataBackup.put("SAVE_ORD_SERVICE_ORDER", serviceOrderList);
            PrincipalLogUtils.addOperationLog(ModuleNames.ORD, ModuleNames.ORD_SERVICE_ORDER, UserActions.UPDATE, "添加服务订单", dataBackup);

        }
    }
}
